<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>new.target属性</title>
</head>
<body>
    <h1>new.target属性</h1>
    <h2>返回new命令作用于的那个构造函数</h2>

    <script>
        // 基本用法
        function Person(name) {
            if (new.target === Person) {
                this.name = name;
            } else {
                throw new Error('必须使用new生成实例');
            }
        }

        // 正确使用
        const person = new Person('张三');
        console.log(person.name); // '张三'

        // 错误使用
        try {
            Person('李四'); // 抛出错误
        } catch (e) {
            console.log(e.message);
        }

        // 在类中使用new.target
        class Shape {
            constructor() {
                if (new.target === Shape) {
                    throw new Error('Shape类不能直接实例化');
                }
            }
        }

        class Rectangle extends Shape {
            constructor(length, width) {
                super();
                this.length = length;
                this.width = width;
            }
        }

        // const shape = new Shape(); // 错误
        const rectangle = new Rectangle(3, 4); // 正确

        // 实际应用：单例模式
        class Singleton {
            static #instance;
            
            constructor() {
                if (new.target !== Singleton) {
                    throw new Error('请使用Singleton.getInstance()');
                }
                if (Singleton.#instance) {
                    throw new Error('Singleton已经实例化');
                }
                Singleton.#instance = this;
            }

            static getInstance() {
                if (!this.#instance) {
                    this.#instance = new Singleton();
                }
                return this.#instance;
            }
        }

        const s1 = Singleton.getInstance();
        const s2 = Singleton.getInstance();
        console.log(s1 === s2); // true
    </script>
</body>
</html> 